package com.macro.mall.tiny.service.Impl;

import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.macro.mall.tiny.common.api.CommonResult;
import com.macro.mall.tiny.common.api.ResponseResult;
import com.macro.mall.tiny.common.utils.JwtUtil;
import com.macro.mall.tiny.common.utils.RedisCache;
import com.macro.mall.tiny.common.utils.RequestUtil;
import com.macro.mall.tiny.dao.UmsAdminRoleRelationDao;
import com.macro.mall.tiny.domain.LoginUser;
import com.macro.mall.tiny.domain.User;
import com.macro.mall.tiny.dto.umsAdminParam;
import com.macro.mall.tiny.dto.updatePasswordDTO;
import com.macro.mall.tiny.mbg.mapper.UmsAdminLoginLogMapper;
import com.macro.mall.tiny.mbg.mapper.UmsAdminMapper;
import com.macro.mall.tiny.mbg.mapper.UmsAdminRoleRelationMapper;
import com.macro.mall.tiny.mbg.model.*;
import com.macro.mall.tiny.service.UmsAdminService;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
public class UmsAdminServiceImpl implements UmsAdminService {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UmsAdminLoginLogMapper umsAdminLoginLogMapper;
    @Autowired
    private UmsAdminMapper umsAdminMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private UmsAdminRoleRelationMapper umsAdminRoleRelationMapper;
    @Autowired
    private UmsAdminRoleRelationDao umsAdminRoleRelationDao;
    @Value("Bearer ")
    private String tokenHead;


    //用户登录
    @Override
    public ResponseResult login(User user) {

        //AuthenticationManager authenticate进行用户认证
        UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
        Authentication authentication=authenticationManager.authenticate(authenticationToken);

        //如果认证没通过，给出相应提示
        if(Objects.isNull(authentication)){
            throw new RuntimeException("登录失败");
        }

        //如果认证通过了，就利用userId生成一个jwt令牌存入ResponseResult返回
        LoginUser loginUser=(LoginUser) authentication.getPrincipal();
        String userId=loginUser.getXxuser().getId().toString();
        String jwt= JwtUtil.createJWT(userId);

        //把完整信息存入redis当中，userId作为key
        redisCache.setCacheObject("Userlogin"+userId,loginUser);

        //添加后台用户登录表信息
        addUmsAdminLoginLog(userId);

        Map<String,String> map=new HashMap<>();
        map.put("token",jwt);
        map.put("tokenHead",tokenHead);
        return new ResponseResult(200,"登录成功",map);
    }

    //添加后台用户登录日志表信息
    private void addUmsAdminLoginLog(String userId) {
        Long longUserId = Long.parseLong(userId);
        UmsAdminLoginLog umsAdminLoginLog=new UmsAdminLoginLog();
        umsAdminLoginLog.setAdminId(longUserId);
        umsAdminLoginLog.setCreateTime(new Date());
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        umsAdminLoginLog.setIp(RequestUtil.getRequestIp(request));

        umsAdminLoginLogMapper.insertSelective(umsAdminLoginLog);
    }

    //退出登录
    @Override
    public CommonResult logout() {
        //获取SecurityContextHolder中的userId
        UsernamePasswordAuthenticationToken authenticationToken=(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser=(LoginUser) authenticationToken.getPrincipal();
        Long userId=loginUser.getXxuser().getId();
        //删除redis当中的值
        redisCache.deleteObject("Userlogin"+userId);

        return CommonResult.success(null);
    }

    //用户注册
    @Override
    public UmsAdmin register(umsAdminParam umsAdminParam) {
        UmsAdmin umsAdmin=new UmsAdmin();
        BeanUtils.copyProperties(umsAdminParam,umsAdmin);
        umsAdmin.setCreateTime(new Date());
        umsAdmin.setStatus(1);

        //先查询有没有相同名字的用户，有的话返回
        UmsAdminExample example=new UmsAdminExample();
        UmsAdminExample.Criteria criteria=example.createCriteria();
        criteria.andUsernameEqualTo(umsAdmin.getUsername());
        List<UmsAdmin> umsAdminList=umsAdminMapper.selectByExample(example);
        if(umsAdminList!=null && umsAdminList.size()>0){
            return null;
        }

        //然后对密码进行加密操作
        String password=passwordEncoder.encode(umsAdmin.getPassword());
        umsAdmin.setPassword(password);

        //没有相同名字的话，直接在数据库中修改数据，返回实体对象
        umsAdminMapper.insertSelective(umsAdmin);
        return umsAdmin;
    }

    //刷新令牌
    @Override
    public String refreshToken(String token) {
        String jwt=token.substring(7);
        if(StringUtils.isEmpty(jwt)){
            return null;
        }
        try {
            jwt=JwtUtil.refreshJwt(jwt);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return jwt;
    }

    //根据用户名查询用户信息
    @Override
    public UmsAdmin selectByUsername(String username) {
        UmsAdminExample example=new UmsAdminExample();
        UmsAdminExample.Criteria criteria=example.createCriteria();

        List<UmsAdmin> umsAdminList= umsAdminMapper.selectByExample(example);
        return umsAdminList.get(0);
    }

    //根据用户名分页获取用户信息
    @Override
    public List<UmsAdmin> getList(String userName, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        UmsAdminExample example=new UmsAdminExample();
        UmsAdminExample.Criteria criteria= example.createCriteria();
        if(!StringUtils.isEmpty(userName)){
            criteria.andUsernameLike("%"+userName+"%");
            example.or(example.createCriteria().andNickNameLike("%"+userName+"%"));
        }
        List<UmsAdmin> umsAdminList=umsAdminMapper.selectByExample(example);

        return umsAdminList;
    }

    //获取指定用户信息
    @Override
    public UmsAdmin getById(Long id) {
        return umsAdminMapper.selectByPrimaryKey(id);
    }

    //修改指定用户信息
    @Override
    public Integer updateById(Long id, UmsAdmin umsAdmin) {
        umsAdmin.setId(id);
        UmsAdmin ums=umsAdminMapper.selectByPrimaryKey(id);
        if(ums.getPassword().equals(umsAdmin.getPassword())){
            umsAdmin.setPassword(null);
        }else{
            if(StrUtil.isEmpty(umsAdmin.getPassword())){
                umsAdmin.setPassword(null);
            }
            else{
                umsAdmin.setPassword(passwordEncoder.encode(umsAdmin.getPassword()));
            }
        }
        Integer code=umsAdminMapper.updateByPrimaryKeySelective(umsAdmin);

        //删除对应缓存数据,删除redis当中的值
        redisCache.deleteObject("Userlogin"+id);

        return code;
    }

    //删除指定用户信息
    @Override
    public Integer deleteById(Long id) {
        //删除数据库中的用户信息
        Integer code=umsAdminMapper.deleteByPrimaryKey(id);
        //删除缓存中的用户信息
        redisCache.deleteObject("Userlogin"+id);
        return code;
    }

    //修改指定用户密码
    @Override
    public Integer updatePassword(updatePasswordDTO updatePasswordDTO) {
        if(StringUtils.isEmpty(updatePasswordDTO.getNewPassword())
        ||StringUtils.isEmpty(updatePasswordDTO.getOldPassword())
        ||StringUtils.isEmpty(updatePasswordDTO.getUsername())){
            return -1;
        }

        //根据用户名查询用户信息
        UmsAdminExample example=new UmsAdminExample();
        UmsAdminExample.Criteria criteria= example.createCriteria();
        criteria.andUsernameEqualTo(updatePasswordDTO.getUsername());
        List<UmsAdmin> umsAdminList=umsAdminMapper.selectByExample(example);
        if(umsAdminList==null || umsAdminList.size()==0){
            return -2;
        }

        //判断提交的原密码是否正确
        UmsAdmin umsAdmin=umsAdminList.get(0);
        if(!passwordEncoder.matches(updatePasswordDTO.getOldPassword(),umsAdmin.getPassword())){
            return -3;
        }
        umsAdmin.setPassword(passwordEncoder.encode(updatePasswordDTO.getNewPassword()));
        Integer code=umsAdminMapper.updateByPrimaryKey(umsAdmin);

        //删除缓存中的数据
        //删除缓存中的用户信息
        redisCache.deleteObject("Userlogin"+umsAdmin.getId());

        return code;
    }

    //给用户分配角色
    @Override
    public Integer updateRole(Long userId, List<Long> roleIds) {
        Integer num = 0;

        //先删除原来的关系
        UmsAdminRoleRelationExample example=new UmsAdminRoleRelationExample();
        UmsAdminRoleRelationExample.Criteria criteria= example.createCriteria();
        criteria.andAdminIdEqualTo(userId);
        umsAdminRoleRelationMapper.deleteByExample(example);

        //建立新关系
        if(!CollectionUtils.isEmpty(roleIds)){
            List<UmsAdminRoleRelation> umsAdminRoleRelationList=new ArrayList<>();
            for(Long roleId:roleIds){
                UmsAdminRoleRelation umsAdminRoleRelation=new UmsAdminRoleRelation();
                umsAdminRoleRelation.setAdminId(userId);
                umsAdminRoleRelation.setRoleId(roleId);
                umsAdminRoleRelationList.add(umsAdminRoleRelation);
            }
            num=umsAdminRoleRelationDao.insertList(umsAdminRoleRelationList);
        }

        //删除缓存数据
        //删除缓存中的用户信息
        redisCache.deleteObject("Userlogin"+userId);

        return num;
    }

    //获取指定用户角色
    @Override
    public List<UmsRole> getRoleByAdminId(Long userId) {
        return umsAdminRoleRelationDao.getRoleList(userId);
    }
}
